import type { PropType } from "vue";
import type {
  BaseProps,
  dateProps,
  inputProps,
  numberProps,
  selectProps
} from "../type";
import Select from "./select.vue";
import { omit } from "lodash-unified";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { isFunction } from "@pureadmin/utils";

export const defProps = {
  formList: {
    type: Array as PropType<any[]>,
    default: () => []
  },
  formData: {
    type: Object as PropType<object>,
    default: () => ({})
  },
  isInline: {
    type: Boolean,
    default: true
  },
  labelWidth: {
    type: [String, Number],
    default: "100px"
  },
  labelPosition: {
    type: String,
    default: "right"
  },
  hiddenBtn: {
    type: Boolean,
    default: false
  },
  showNumber: {
    type: Number,
    default: 6
  },
  hasUnfold: {
    type: Boolean,
    default: true
  },
  isAutoSearch: {
    type: Boolean,
    default: false
  },
  exportBtnFlag: {
    type: Boolean,
    default: false
  }
};

function inputHandle(option: inputProps) {
  const { inType, ...rest } = option;
  return {
    component: "el-input",
    label: option.label,
    prop: option.key,
    maxlength: inType === "textarea" ? 100 : 30,
    // showWordLimit: true,
    ...rest,
    type: inType ?? "text"
  };
}

function numberHandle(option: numberProps) {
  return {
    component: "el-input-number",
    label: option.label,
    prop: option.key,
    ...option
  };
}

function selectHandle(option: selectProps) {
  return {
    component: Select,
    emptyValues: [null, undefined],
    filterable: true,
    ...option
  };
}

function dateHandle(option: dateProps) {
  const { inType, type, ...rest } = option;
  return {
    component: "el-date-picker",
    type: inType ?? type,
    rangSeparator: "-",
    startPlaceholder: "请选择开始时间",
    endPlaceholder: "请选择结束时间",
    prefixIcon: useRenderIcon("tdesign:time"),
    ...rest
  };
}

function baseHandle(option: BaseProps) {
  return {
    component: option.type,
    style: "width: 100%",
    ...option,
    type: option.inType
  };
}

const handleGather = {
  input: inputHandle,
  select: selectHandle,
  date: dateHandle,
  number: numberHandle,
  base: baseHandle
};

function ruleHandle(
  item: BaseProps,
  { t, te }: { t: (key: string) => string; te: (key: string) => boolean }
) {
  item.rules = item?.rules ?? [];
  if (item.required) {
    if (!item.rules.find(item => item.required)) {
      const isInput = ["input", "number"].includes(item.type);
      item.rules.push({
        required: true,
        message: `${isInput ? t("formula_detail.please_input") : t("formula_detail.please_select")}${
          te(item.label) ? t(item.label) : item.label
        }`,
        trigger: "change"
      });
    } else {
      const index = item.rules.findIndex(item => item.required);
      if (index !== -1) {
        const isInput = ["input", "number"].includes(item.type);
        item.rules[index].message =
          `${isInput ? t("formula_detail.please_input") : t("formula_detail.please_select")}${
            te(item.label) ? t(item.label) : item.label
          }`;
      }
    }
  }
  console.log("item", item);
  return item;
}

/**
 * 计算文本宽度
 * @param {string} text - 要计算宽度的文本
 * @param {string} font - 字体样式，例如 '14px Arial'
 * @return {number} 文本宽度(px)
 */
function getTextWidth(text, font) {
  // 创建 canvas 元素
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");

  // 设置字体样式
  context.font = font || getComputedStyle(document.body).font;

  // 测量文本宽度
  const metrics = context.measureText(text);
  return metrics.width;
}

/**
 * 从数组中找出渲染后宽度最长的文本
 * @param {Array<string>} texts - 文本数组
 * @param {string} font - 字体样式
 * @return {Object} 包含最长文本及其宽度的对象
 */
function findLongestText(texts, font) {
  if (!texts || texts.length === 0) {
    return { text: "", width: 0 };
  }

  let maxWidth = 0;
  let longestText = texts[0];

  texts.forEach(text => {
    const width = getTextWidth(text, font);
    if (width > maxWidth) {
      maxWidth = width;
      longestText = text;
    }
  });

  return {
    text: longestText,
    width: maxWidth
  };
}

const setMaxLabelWidth = (props, t) => {
  let maxLabelWidth = 0;
  const textArray = [];
  for (const item of props.formList) {
    textArray.push(t(item.label));
  }
  if (textArray.length > 0) {
    const { width } = findLongestText(textArray, "14px Arial");
    maxLabelWidth = width + 30;
  }
  return maxLabelWidth;
};

export async function handleFormList(
  formList: BaseProps[],
  props: any,
  { t, te }: any
) {
  const list = formList.map(async item => {
    if (isFunction(item)) {
      item = await (item as Function)();
    }

    const { type } = ruleHandle(item, { t, te });

    if (handleGather[type]) {
      const itemGather = handleGather[type](item);
      itemGather.labelWidth =
        props.isInline && props.labelWidth === "100px"
          ? "auto"
          : setMaxLabelWidth(props, t);
      return itemGather;
    } else {
      const itemGather = handleGather["base"](item);
      itemGather.labelWidth =
        props.isInline && props.labelWidth === "100px"
          ? "auto"
          : setMaxLabelWidth(props, t);
      return itemGather;
    }
  });
  return await Promise.all(list);
}

export function handleDefValue(formList: (inputProps | selectProps)[]) {
  const defValue: any = {};
  formList.forEach(item => {
    const { key, defaultValue } = item;
    defValue[key] = defaultValue;
  });
  return defValue;
}

export const propOmit = (item: any) => {
  const rest = ["component", "label", "key", "prop", "compLabel", "onChange"];
  return omit(item, rest);
};

export const remainingSpan = (
  formList: (inputProps | selectProps)[],
  isInline: boolean
) => {
  if (!isInline) return 24;
  let _span = 0;
  formList.forEach(item => {
    const { span } = item;
    _span += span ?? 6;
  });
  const remaining = _span % 24;
  return remaining === 0 ? 24 : 24 - remaining;
};

export const isMarginTop = (
  formList: (inputProps | selectProps)[],
  index: number,
  isInline: boolean
) => {
  if (!isInline) return false;
  let _span = 0;
  formList.forEach((item, i) => {
    const { span } = item;
    if (i < index) {
      _span += span ?? 6;
    } else {
      return;
    }
  });
  return _span > 24;
};
